package com.axones.planningpoker.dao;

import java.util.Iterator;

import com.axones.planningpoker.bean.User;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;

public class UserDAO {
	private static final String KIND_NAME = "User";

	public long add(User user) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		synchronized (this) {
			if (find(user.getEmail()) != null) {
				return -1;
			}

			return datastore.put(convert(user)).getId();
		}
	}

	public void delete(long id) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Key k = KeyFactory.createKey(KIND_NAME, id);

		datastore.delete(k);
	}

	public User get(long userId) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Key k = KeyFactory.createKey(KIND_NAME, userId);

		try {
			return convert(datastore.get(k));
		} catch (EntityNotFoundException e) {
			return null;
		}
	}

	public User find(String email, String password) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Query q = new Query(KIND_NAME);
		q.addFilter("email", Query.FilterOperator.EQUAL, email);
		q.addFilter("password", Query.FilterOperator.EQUAL, password);

		PreparedQuery pq = datastore.prepare(q);

		Iterable<Entity> results = pq.asIterable();
		Iterator<Entity> it = results.iterator();

		if (!it.hasNext()) {
			return null;
		}

		Entity pu = it.next();

		if (it.hasNext()) {
			return null;
		}

		return convert(pu);
	}

	public User find(String email) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Query q = new Query(KIND_NAME);
		q.addFilter("email", Query.FilterOperator.EQUAL, email);

		PreparedQuery pq = datastore.prepare(q);

		Iterable<Entity> results = pq.asIterable();
		Iterator<Entity> it = results.iterator();

		if (!it.hasNext()) {
			return null;
		}

		Entity pu = results.iterator().next();

		return convert(pu);
	}

	public String update(User user) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Key k = KeyFactory.createKey(KIND_NAME, user.getId());

		Entity u;

		try {
			u = datastore.get(k);
		} catch (EntityNotFoundException e) {
			return "not.found";
		}

		User userDB = find(user.getEmail());
		if (userDB != null && userDB.getId() != user.getId()) {
			return "email.used";
		}

		update(user, u);

		datastore.put(u);

		return "ok";
	}

	private User convert(Entity i) {
		User user = new User();

		user.setId(i.getKey().getId());

		user.setDisplayName((String) i.getProperty("displayName"));
		user.setEmail((String) i.getProperty("email"));
		user.setPassword((String) i.getProperty("password"));

		return user;
	}

	private Entity convert(User user) {
		Entity u = new Entity(KIND_NAME);

		u.setProperty("displayName", user.getDisplayName());
		u.setProperty("email", user.getEmail());
		u.setProperty("password", user.getPassword());

		return u;
	}

	private void update(User user, Entity u) {
		u.setProperty("displayName", user.getDisplayName());
		u.setProperty("email", user.getEmail());
		u.setProperty("password", user.getPassword());
	}
}
